package com.tanklab.signature.common.util;


import com.tanklab.signature.eth.contract.Safemath;
import okhttp3.OkHttpClient;
import org.web3j.crypto.Credentials;
import org.web3j.protocol.Web3j;
import org.web3j.protocol.core.RemoteCall;
import org.web3j.protocol.core.methods.response.TransactionReceipt;
import org.web3j.protocol.core.methods.response.Web3ClientVersion;
import org.web3j.protocol.http.HttpService;
import org.web3j.tx.Contract;
import org.web3j.tx.RawTransactionManager;
import org.web3j.tx.TransactionManager;
import com.tanklab.signature.eth.contract.Abroad;
import org.web3j.tx.gas.StaticGasProvider;

import java.io.IOException;
import java.math.BigInteger;
import java.util.concurrent.TimeUnit;

/**
 * <p>
 * TODO:区块链操作
 * </p>
 *
 * @author Zhiyuan Zheng
 * @since 2023-07-28
 */
/*
    主要用于处理有关牛和牛肉的区块链操作:
    addOxBlockchain: 将牛的信息上传到区块链，包括牛的ID、品种、结束时间等。
    addBeefBlockchain: 将牛肉的信息上传到区块链，包括牛肉的ID、加工时间、运输信息等。
    sellBeefBlockchain: 记录牛肉的销售信息到区块链，包括出售时间、地点、价格等。
    queryCowBlockchain: 查询区块链中存储的牛的信息。
    getheight: 查询区块链的当前块高度。
    每个方法通过连接到区块链节点，使用智能合约的方法来执行相应操作。
 */
public class BlockchainOperation {

    public static String addOxBlockchain(
            CityBlock cb,
            String ox_key,
            BigInteger ox_id,
            String breed,
            String end_time,
            BigInteger feeding_period,
            BigInteger weight,
            String location,
            String feed_person
    ){

        String netWorkUrl = cb.netWorkUrl;
        String walletKey = cb.walletKey;
        String contractAddress = BlockchainConfig.ox_contractAddress;
        long chainId = cb.chainId;
        try {
            //连接对应节点
            System.out.println("Uploading data to blockchain...");
            Web3j web3 = Web3j.build(new HttpService(netWorkUrl));
            Web3ClientVersion web3clientversion = web3.web3ClientVersion().send();
            Credentials credentials = Credentials.create(walletKey);
            TransactionManager transactionManager = new RawTransactionManager(
                    web3, credentials,chainId);
            BigInteger gasPrice = web3.ethGasPrice().send().getGasPrice();
            Abroad contract = Abroad.load(contractAddress,web3,
                    transactionManager,new StaticGasProvider(gasPrice, Contract.GAS_LIMIT));
            //调用合约方法
            RemoteCall<TransactionReceipt> setWord = contract.addCow(ox_key, ox_id, breed, end_time, feeding_period, weight, location, feed_person);

            TransactionReceipt transactionReceipt = setWord.send();
            String transactionHash = transactionReceipt.getTransactionHash();
            System.out.println("[Successfully Upload]\n"+transactionHash);
            return transactionHash;
        }catch (Exception e){
            e.printStackTrace();
        }
        return "error";
    }

    public static String addBeefBlockchain(
            CityBlock cb,
            String beef_key,
            BigInteger beef_id,
            String breed,
            String process_time,
            String process_place,
            String process_person,
            String transport_time,
            String transport_place,
            String transport_person,
            BigInteger ox_id
    ){
        String netWorkUrl = cb.netWorkUrl;
        String walletKey = cb.walletKey;
        String contractAddress = BlockchainConfig.ox_contractAddress;
        long chainId = cb.chainId;
        try {
            //连接对应节点
            System.out.println("Uploading data to blockchain...");
            Web3j web3 = Web3j.build(new HttpService(netWorkUrl));
            Web3ClientVersion web3clientversion = web3.web3ClientVersion().send();
            Credentials credentials = Credentials.create(walletKey);
            TransactionManager transactionManager = new RawTransactionManager(
                    web3, credentials,chainId);
            BigInteger gasPrice = web3.ethGasPrice().send().getGasPrice();
            Abroad contract = Abroad.load(contractAddress,web3,
                    transactionManager,new StaticGasProvider(gasPrice, Contract.GAS_LIMIT));
            //调用合约方法
            RemoteCall<TransactionReceipt> setWord = contract.addBeef(beef_key, beef_id, breed, process_time, process_place, process_person, transport_time, transport_place, transport_person, ox_id);

            TransactionReceipt transactionReceipt = setWord.send();
            String transactionHash = transactionReceipt.getTransactionHash();
            System.out.println("[Successfully Upload]\n"+transactionHash);
            return transactionHash;
        }catch (Exception e){
            e.printStackTrace();
        }
        return "error";
    }

    public static String sellBeefBlockchain(
            CityBlock cb,
            String beef_key,
            BigInteger beef_id,
            String transfer_time,
            String transfer_place,
            String transfer_person,
            String sell_place,
            BigInteger price,
            BigInteger weight,
            String quality_guarantee_time,
            BigInteger ox_id
    ){
        String netWorkUrl = cb.netWorkUrl;
        String walletKey = cb.walletKey;
        String contractAddress = BlockchainConfig.beef_contractAddress;
        long chainId = cb.chainId;
        try {
            //连接对应节点
            System.out.println("Uploading data to blockchain...");
            Web3j web3 = Web3j.build(new HttpService(netWorkUrl));
            Web3ClientVersion web3clientversion = web3.web3ClientVersion().send();
            Credentials credentials = Credentials.create(walletKey);
            TransactionManager transactionManager = new RawTransactionManager(
                    web3, credentials,chainId);
            BigInteger gasPrice = web3.ethGasPrice().send().getGasPrice();
            Safemath contract = Safemath.load(contractAddress,web3,
                    transactionManager,new StaticGasProvider(gasPrice, Contract.GAS_LIMIT));
            //调用合约方法
            RemoteCall<TransactionReceipt> setWord = contract.sellBeef(beef_key, beef_id, transfer_time, transfer_place, transfer_person, sell_place, price, weight, quality_guarantee_time, ox_id);

            TransactionReceipt transactionReceipt = setWord.send();
            String transactionHash = transactionReceipt.getTransactionHash();
            System.out.println("[Successfully Upload]\n"+transactionHash);
            return transactionHash;
        }catch (Exception e){
            e.printStackTrace();
        }
        return "error";
    }

    public static void queryCowBlockchain(
            CityBlock cb,
            String ox_key
    ){
        String netWorkUrl = cb.netWorkUrl;
        String walletKey = cb.walletKey;
        String contractAddress = BlockchainConfig.ox_contractAddress;
        long chainId = cb.chainId;
        try {
            //连接对应节点
            Web3j web3 = Web3j.build(new HttpService(netWorkUrl));
            Web3ClientVersion web3clientversion = web3.web3ClientVersion().send();
            Credentials credentials = Credentials.create(walletKey);
            TransactionManager transactionManager = new RawTransactionManager(
                    web3, credentials,chainId);
            BigInteger gasPrice = web3.ethGasPrice().send().getGasPrice();
            Abroad contract = Abroad.load(contractAddress,web3,
                    transactionManager,new StaticGasProvider(gasPrice, Contract.GAS_LIMIT));
            //调用合约方法
            System.out.println(contract.queryCow(ox_key).send().component1());
        }catch (Exception e){
            e.printStackTrace();
        }
    }

    public static void getheight(){
        String ip = "1.92.121.165:10012";
        try {
            // 创建 OkHttpClient 实例，并设置超时时间
            OkHttpClient.Builder builder = new OkHttpClient.Builder()
                    .connectTimeout(500, TimeUnit.SECONDS)
                    .readTimeout(500, TimeUnit.SECONDS);

            // 创建自定义的 HttpService，并传入 OkHttpClient 实例
            HttpService httpService = new HttpService("http://1.92.121.165:10012", builder.build());
            // HttpService httpService = new
            // HttpService(String.valueOf("http://116.204.36.31:10012"), builder.build());
            // 创建 Web3j 实例
            Web3j web3j = Web3j.build(httpService);

            // 查询该链的块高
            BigInteger blockHeight = web3j.ethBlockNumber().send().getBlockNumber();
            System.out.println(blockHeight);
        } catch (IOException e) {
            e.printStackTrace();
            System.out.println("error");
        }
    }

    public static void main(String[] args) {
        getheight();
//        Date date = new Date();
//        SimpleDateFormat sdf = new SimpleDateFormat("yyyy-MM-dd HH:mm:ss.SSS");
//        String formattedDate = sdf.format(date);
//        System.out.println(formattedDate);
//        String txid = addBeefBlockchain(CityBlock.Paris,"12312313",new BigInteger(String.valueOf(100)),"111","2023-12-12","Paris","zzy","2023-12-12","Tianjin","zzy",new BigInteger(String.valueOf(220)));
////        String transactionId = addOxBlockchain(CityBlock.Paris,"12345621372138190", new BigInteger(String.valueOf(100)),"Yak","2023-07-26",new BigInteger(String.valueOf(40)),new BigInteger(String.valueOf(220)),"Paris","zzy");
////        System.out.println(transactionId);
//        System.out.println(txid);
//        Date date1 = new Date();
//        SimpleDateFormat sdf1 = new SimpleDateFormat("yyyy-MM-dd HH:mm:ss.SSS");
//        String formattedDate1 = sdf.format(date1);
//        System.out.println(formattedDate1);
//        long delta = date1.getTime()-date.getTime();
//        System.out.println(delta);

        //        queryCowBlockchain("3e66b6bafeb7c3f5b551ba3dbb888f87e0726cc357c33bed328390a303f2cde1");
    }
}
